package gxt.visual.util;

import java.util.Collection;
import java.util.Map;

/**
 * @author ervin
 */
public abstract class Assert{
	
	/**
	 * Assert a boolean expression, throwing <code>IllegalArgumentException</code> if the test result is <code>false</code>.
	 * 
	 * <pre class="code">
	 * Assert.isTrue( i &gt; 0, &quot;The value must be greater than zero&quot; );
	 * </pre>
	 * @param expression a boolean expression
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if expression is <code>false</code>
	 */
	public static void isTrue( final boolean expression, final String message ){
		if( !expression ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Assert a boolean expression, throwing <code>IllegalArgumentException</code> if the test result is <code>false</code>.
	 * 
	 * <pre class="code">
	 * Assert.isTrue( i &gt; 0 );
	 * </pre>
	 * @param expression a boolean expression
	 * @throws IllegalArgumentException if expression is <code>false</code>
	 */
	public static void isTrue( final boolean expression ){
		Assert.isTrue( expression, "[Assertion failed] - this expression must be true" );
	}
	
	/**
	 * Assert that an object is <code>null</code> .
	 * 
	 * <pre class="code">
	 * Assert.isNull( value, &quot;The value must be null&quot; );
	 * </pre>
	 * @param object the object to check
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if the object is not <code>null</code>
	 */
	public static void isNull( final Object object, final String message ){
		if( object != null ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Assert that an object is <code>null</code> .
	 * 
	 * <pre class="code">
	 * Assert.isNull( value );
	 * </pre>
	 * @param object the object to check
	 * @throws IllegalArgumentException if the object is not <code>null</code>
	 */
	public static void isNull( final Object object ){
		Assert.isNull( object, "[Assertion failed] - the object argument must be null" );
	}
	
	/**
	 * Assert that an object is not <code>null</code> .
	 * 
	 * <pre class="code">
	 * Assert.notNull( clazz, &quot;The class must not be null&quot; );
	 * </pre>
	 * @param object the object to check
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if the object is <code>null</code>
	 */
	public static void notNull( final Object object, final String message ){
		if( object == null ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Assert that an object is not <code>null</code> .
	 * 
	 * <pre class="code">
	 * Assert.notNull( clazz );
	 * </pre>
	 * @param object the object to check
	 * @throws IllegalArgumentException if the object is <code>null</code>
	 */
	public static void notNull( final Object object ){
		Assert.notNull( object, "[Assertion failed] - this argument is required; it must not be null" );
	}
	
	/**
	 * Assert that the given String is not empty; that is, it must not be <code>null</code> and not the empty String.
	 * 
	 * <pre class="code">
	 * Assert.hasLength( name, &quot;Name must not be empty&quot; );
	 * </pre>
	 * @param str the String to check
	 * @param message the exception message to use if the assertion fails
	 */
	public static void hasLength( final String str, final String message ){
		if( Assert.hasLengthImpl( str ) ){
			throw new IllegalArgumentException( message );
		}
	}
	/**
	 * Assert that the given String is not empty; that is, it must not be <code>null</code> and not the empty String.
	 * 
	 * <pre class="code">
	 * Assert.hasLength( name, &quot;Name must not be empty&quot; );
	 * </pre>
	 * @param str the String to check
	 * @return
	 */
	private static boolean hasLengthImpl( final String str ){
		return ( ( str != null ) && ( str.length() > 0 ) );
	}
	
	/**
	 * Assert that the given String is not empty; that is, it must not be <code>null</code> and not the empty String.
	 * 
	 * <pre class="code">
	 * Assert.hasLength( name );
	 * </pre>
	 * @param text the String to check
	 */
	public static void hasLength( final String text ){
		Assert.hasLength( text, "[Assertion failed] - this String argument must have length; it must not be null or empty" );
	}
	
	/**
	 * Assert that the given String has valid text content; that is, it must not be <code>null</code> and must contain at least one non-whitespace character.
	 * 
	 * <pre class="code">
	 * Assert.hasText( name, &quot;'name' must not be empty&quot; );
	 * </pre>
	 * @param text the String to check
	 * @param message the exception message to use if the assertion fails
	 */
	public static void hasText( final String text, final String message ){
		if( !Assert.hasTextImpl( text ) ){
			throw new IllegalArgumentException( message );
		}
	}
	
	private static boolean hasTextImpl( final String text ){
		return ( ( text != null ) && ( text.trim().length() > 0 ) );
	}
	
	/**
	 * Assert that the given String has valid text content; that is, it must not be <code>null</code> and must contain at least one non-whitespace character.
	 * 
	 * <pre class="code">
	 * Assert.hasText( name, &quot;'name' must not be empty&quot; );
	 * </pre>
	 * @param text the String to check
	 */
	public static void hasText( final String text ){
		Assert.hasText( text, "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank" );
	}
	
	/**
	 * Assert that the given text does not contain the given substring.
	 * 
	 * <pre class="code">
	 * Assert.doesNotContain( name, &quot;rod&quot;, &quot;Name must not contain 'rod'&quot; );
	 * </pre>
	 * @param textToSearch the text to search
	 * @param substring the substring to find within the text
	 * @param message the exception message to use if the assertion fails
	 */
	public static void doesNotContain( final String textToSearch, final String substring, final String message ){
		if( Assert.hasLengthImpl( textToSearch ) && Assert.hasLengthImpl( substring ) && ( textToSearch.indexOf( substring ) != -1 ) ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Assert that the given text does not contain the given substring.
	 * 
	 * <pre class="code">
	 * Assert.doesNotContain( name, &quot;rod&quot; );
	 * </pre>
	 * @param textToSearch the text to search
	 * @param substring the substring to find within the text
	 */
	public static void doesNotContain( final String textToSearch, final String substring ){
		Assert.doesNotContain( textToSearch, substring, "[Assertion failed] - this String argument must not contain the substring [" + substring + "]" );
	}
	
	/**
	 * Assert that an array has elements; that is, it must not be <code>null</code> and must have at least one element.
	 * 
	 * <pre class="code">
	 * Assert.notEmpty( array, &quot;The array must have elements&quot; );
	 * </pre>
	 * @param array the array to check
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
	 */
	public static void notEmpty( final Object[] array, final String message ){
		if( Assert.isEmptyImpl( array ) ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Determine whether the given array is empty: i.e. <code>null</code> or of zero length.
	 * @param array the array to check
	 */
	public static boolean isEmptyImpl( final Object[] array ){
		return ( ( array == null ) || ( array.length == 0 ) );
	}
	
	/**
	 * Assert that an array has elements; that is, it must not be <code>null</code> and must have at least one element.
	 * 
	 * <pre class="code">
	 * Assert.notEmpty( array );
	 * </pre>
	 * @param array the array to check
	 * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
	 */
	public static void notEmpty( final Object[] array ){
		Assert.notEmpty( array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element" );
	}
	
	/**
	 * Assert that an array has no null elements. Note: Does not complain if the array is empty!
	 * 
	 * <pre class="code">
	 * Assert.noNullElements( array, &quot;The array must have non-null elements&quot; );
	 * </pre>
	 * @param array the array to check
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if the object array contains a <code>null</code> element
	 */
	public static void noNullElements( final Object[] array, final String message ){
		if( array != null ){
			for( final Object element : array ){
				if( element == null ){
					throw new IllegalArgumentException( message );
				}
			}
		}
	}
	
	/**
	 * Assert that an array has no null elements. Note: Does not complain if the array is empty!
	 * 
	 * <pre class="code">
	 * Assert.noNullElements( array );
	 * </pre>
	 * @param array the array to check
	 * @throws IllegalArgumentException if the object array contains a <code>null</code> element
	 */
	public static void noNullElements( final Object[] array ){
		Assert.noNullElements( array, "[Assertion failed] - this array must not contain any null elements" );
	}
	
	/**
	 * Assert that a collection has elements; that is, it must not be <code>null</code> and must have at least one element.
	 * 
	 * <pre class="code">
	 * Assert.notEmpty( collection, &quot;Collection must have elements&quot; );
	 * </pre>
	 * @param collection the collection to check
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
	 */
	public static void notEmpty( final Collection collection, final String message ){
		if( Assert.isEmptyImpl( collection ) ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Return <code>true</code> if the supplied Collection is <code>null</code> or empty. Otherwise, return <code>false</code>.
	 * @param collection the Collection to check
	 * @return whether the given Collection is empty
	 */
	public static boolean isEmptyImpl( final Collection collection ){
		return ( ( collection == null ) || collection.isEmpty() );
	}
	
	/**
	 * Return <code>true</code> if the supplied Map is <code>null</code> or empty. Otherwise, return <code>false</code>.
	 * @param map the Map to check
	 * @return whether the given Map is empty
	 */
	public static boolean isEmptyImpl( final Map map ){
		return ( ( map == null ) || map.isEmpty() );
	}
	
	/**
	 * Assert that a collection has elements; that is, it must not be <code>null</code> and must have at least one element.
	 * 
	 * <pre class="code">
	 * Assert.notEmpty( collection, &quot;Collection must have elements&quot; );
	 * </pre>
	 * @param collection the collection to check
	 * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
	 */
	public static void notEmpty( final Collection collection ){
		Assert.notEmpty( collection, "[Assertion failed] - this collection must not be empty: it must contain at least 1 element" );
	}
	
	/**
	 * Assert that a Map has entries; that is, it must not be <code>null</code> and must have at least one entry.
	 * 
	 * <pre class="code">
	 * Assert.notEmpty( map, &quot;Map must have entries&quot; );
	 * </pre>
	 * @param map the map to check
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalArgumentException if the map is <code>null</code> or has no entries
	 */
	public static void notEmpty( final Map map, final String message ){
		if( Assert.isEmptyImpl( map ) ){
			throw new IllegalArgumentException( message );
		}
	}
	
	/**
	 * Assert that a Map has entries; that is, it must not be <code>null</code> and must have at least one entry.
	 * 
	 * <pre class="code">
	 * Assert.notEmpty( map );
	 * </pre>
	 * @param map the map to check
	 * @throws IllegalArgumentException if the map is <code>null</code> or has no entries
	 */
	public static void notEmpty( final Map map ){
		Assert.notEmpty( map, "[Assertion failed] - this map must not be empty; it must contain at least one entry" );
	}
	
	/**
	 * Assert a boolean expression, throwing <code>IllegalStateException</code> if the test result is <code>false</code>. Call isTrue if you wish to throw IllegalArgumentException on an assertion failure.
	 * 
	 * <pre class="code">
	 * Assert.state( id == null, &quot;The id property must not already be initialized&quot; );
	 * </pre>
	 * @param expression a boolean expression
	 * @param message the exception message to use if the assertion fails
	 * @throws IllegalStateException if expression is <code>false</code>
	 */
	public static void state( final boolean expression, final String message ){
		if( !expression ){
			throw new IllegalStateException( message );
		}
	}
	
	/**
	 * Assert a boolean expression, throwing {@link IllegalStateException} if the test result is <code>false</code>.
	 * <p>
	 * Call {@link #isTrue(boolean)} if you wish to throw {@link IllegalArgumentException} on an assertion failure.
	 * 
	 * <pre class="code">
	 * Assert.state( id == null );
	 * </pre>
	 * @param expression a boolean expression
	 * @throws IllegalStateException if the supplied expression is <code>false</code>
	 */
	public static void state( final boolean expression ){
		Assert.state( expression, "[Assertion failed] - this state invariant must be true" );
	}
	
}
